package com.lagou.server;

import com.lagou.registry.RegistryInfo;
import com.lagou.registry.ZookeeperRegistryClient;
import com.lagou.server.codec.RpcFrameDecoder;
import com.lagou.server.codec.RpcFrameEncoder;
import com.lagou.server.codec.RpcProtocolDecoder;
import com.lagou.server.codec.RpcProtocolEncoder;
import com.lagou.server.handler.RpcServerProcessHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NettyRpcServer implements  Server {

    Logger logger = LoggerFactory.getLogger(getClass().getName());

    NioEventLoopGroup bossGroup;
    NioEventLoopGroup workGroup;

    public volatile boolean isRunning = false;

    //注册表客户端
    ZookeeperRegistryClient registryClient;

    private String host;
    private int port;

    public NettyRpcServer(String host,int port){
        this.host = host;
        this.port = port;
        registryClient =  ZookeeperRegistryClient.getInstance();
        registryClient.setServer(this);
    }


    @Override
    public void start() {
        if(!isRunning) {
            isRunning = true;
            ServerBootstrap serverBootstrap = new ServerBootstrap();

            serverBootstrap.channel(NioServerSocketChannel.class);
            serverBootstrap.option(NioChannelOption.SO_BACKLOG, 1024);
            serverBootstrap.childOption(NioChannelOption.TCP_NODELAY, true);
            serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));

            //thread
            bossGroup = new NioEventLoopGroup(0, new DefaultThreadFactory("boss"));
            workGroup = new NioEventLoopGroup(0, new DefaultThreadFactory("worker"));
            serverBootstrap.group(bossGroup, workGroup);

            //log
            LoggingHandler debugLogHandler = new LoggingHandler(LogLevel.DEBUG);
            // LoggingHandler infoLogHandler = new LoggingHandler(LogLevel.INFO);

            serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
                @Override
                protected void initChannel(NioSocketChannel ch) throws Exception {

                    ChannelPipeline pipeline = ch.pipeline();

                    pipeline.addLast("debegLog", debugLogHandler);

                    pipeline.addLast("frameDecoder", new RpcFrameDecoder());
                    pipeline.addLast("frameEncoder", new RpcFrameEncoder());

                    pipeline.addLast("protocolDecoder", new RpcProtocolDecoder());
                    pipeline.addLast("protocolEncoder", new RpcProtocolEncoder());
                    pipeline.addLast(new RpcServerProcessHandler());
                }
            });

            try {
                ChannelFuture channelFuture = serverBootstrap.bind(host, port).sync();

                logger.info("服务器已启动...............");
                channelFuture.channel().closeFuture().sync();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void stop() {
        isRunning = false;
        bossGroup.shutdownGracefully();
        workGroup.shutdownGracefully();
    }

    @Override
    public void register(Class service, Class serviceImpl) {
        registryClient.register( new RegistryInfo(host,port,service.getName(), serviceImpl.getName()));
    }


}
